<template>
  <div>
    <!-- 有的时候不需要局部刷新, 而是页面全部刷新, 但是路径我们要写一个孩子路由的形式, 就用一级路由, 但是路径写'/cinemas/search' -->
    <!-- <router-link to="/cinemas/search" custom v-slot="{ navigate, isActive }">
      <li @click="navigate" :class="isActive ? 'fqm-active' : ''">
        search
      </li>
    </router-link> -->

    <!-- px转化为rem，见vant官网进阶语法，他需要配置文件分开似乎，我开始就集合配置了，下次要弄清楚 -->
    <div class="header">
      <van-nav-bar title="影院" ref="header">
        <template #left>
          <div @click="changeCity()">
            <span class="city"
              >{{ $store.state.cityName }} <van-icon name="arrow-down"
            /></span>
          </div>
        </template>
        <template #right>
          <van-icon
            name="search"
            size="20"
            color="black"
            @click="handleSearch()"
          />
        </template>
      </van-nav-bar>
    </div>
    <div class="content-box" :style="{ height }">
      <ul>
        <li
          class="cinema"
          v-for="(cinema, index) in this.$store.state.cinemas"
          :key="index"
        >
          <span class="name">{{ cinema.name }}</span>
          <div class="price">
            ￥<span class="price-number">{{ cinema.lowPrice / 100 }}</span
            >起
          </div>
          <div class="address">{{ cinema.address }}</div>
          <span class="cross-line" />
        </li>
      </ul>
    </div>
  </div>
</template>

<script>
import betterScroll from 'better-scroll'
import Vue from 'vue'
import { mapState, mapActions, mapMutations } from 'vuex'
import { NavBar, icon } from 'vant'

Vue.use(NavBar).use(icon)

export default {
  created () {
    // this指向本组件对象
    console.log(this)
  },
  data () {
    return {
      height: '0px'
    }
  },
  computed: {
    // 这mapState就相当于把store/index.js里states的cinemas的状态直接映射到本组件中(拷贝一份)，同名也叫cinemas
    // 再mounted中我已经打印，可以看看结果,哪里讲了原理
    // mapState(["cinemas"])返回一个对象, 而把这个对象解构到computed中,这个方法就可以直接使用了,名字就是cinemas
    ...mapState(['cinemas'])
  },
  methods: {
    getSCrollHeight () {
      // 注意元素的style或class等等如果既受到dom直接操作的影响，有收到data状态绑定的影响，那么就会冲突
      // 这里使用了节点操作，也可以使用ref，但是navigation在另一个vue中，对于不同组件的信息共享可以使用vuex
      // console.log(document.querySelector(".navigation"));
      this.height =
        document.documentElement.clientHeight -
        this.$refs.header.$el.offsetHeight -
        // 这里没有用document.querySelector(".navigation").offsetHeight，
        // 因为tabBar或者.navigation节点什么时候才能销毁完毕不知道，也就是什么时候从search或者city里出来后把tabBar重新显示不知道
        // 这个时候没有一个时机让我明确的直到tabBar重新显示了，可以再次取他的高度了，因此可能取到null.offsetHeight
        // 所以我干脆直接在App.vue的tabBar显示的时候就直接取高度，存在公共状态里就行了
        // 我试过直接在mounted中document.querySelector(".navigation").offsetHeight直接用，出现了问题了，这个时候还在走销毁程序，
        // destoreyed 内部的方法还没有执行，tabBar没有存在，这个时候document.querySelector(".navigation")还是空的
        // this.$store.state.navBarHeight   //对不起我真是个傻逼，直接v-show不就行了，这样就不为空了，之前用的v-if
        document.querySelector('.navigation').offsetHeight +
        'px'
      console.log(this.height)
    },
    changeCity () {
      this.$router.push('/city')
    },
    handleSearch () {
      this.$router.push('/cinemas/search')
    },
    // 个也是同理mapActions方法返回一个对象,对象的key就是store里action同名方法名字, value是方法函数
    // 原理和mapState一样,不多做赘述
    ...mapActions(['getCinemas'])
  },
  mounted () {
    // 原来实在这里直接document.querySelector(".navigation").offsetHeight, 获取navBar组件的高度, 来计算betterScroll的高度,
    // 但是刚刚进来的时候,或者刚刚从search/city页面换进来的时候,destory还在执行, 这个时候仍然没有把navBar再vuex的公共显示状态
    // 也就是state里的isNavShow设置为true，所以这个时候document.querySelector(".navigation")是空的，报错，因此放在
    this.getSCrollHeight()

    // 这里是原来直接请求，但是由于search页面的数据和cinema完全一致，因此，直接使用Vuex做存储，而不必每次请求，
    // 因为city其实是很少变化的，可以缓存在vuex中，search也可以直接使用，更加方便

    // http({
    //   url: `/gateway?cityId=${this.$store.state.cityId}&ticketFlag=1&k=6463571`,
    //   headers: {
    //     "X-Host": "mall.film-ticket.cinema.list",
    //   },
    // }).then((res) => {
    //   console.log(res);
    //   this.cinemas = res.data.data.cinemas;
    //   // console.log(this.cinemas);
    //   // console.log(document.getElementsByTagName("li").length);
    //   this.$nextTick(() => {
    //     // console.log(document.getElementsByClassName("cinema").length);
    //     // betterScroll优化滚动条
    //     this.getSCrollHeight()
    //     new betterScroll(".content-box", {
    //       scrollbar: {
    //         fade: true,
    //       },
    //     });
    //   });
    // });

    // -------------------------vuex新写法----------------------------
    // 这里可以看到打印到控制台是: {cinemas: ƒ}
    // 可以知道整个方法的第一个参数：一个数组，里面全部都是对应state里的数据名，映射到本组件的同名，作为key，而value是一个方法
    console.log(mapState(['cinemas', 'cityId']))
    // 这个方法就会renturn对应的state的数据, 而把这个对象解构到computed中,这个方法就可以直接使用了,名字就是cinemas
    console.log(mapState(['cinemas']).cinemas)

    // 使用Vuex的action做异步请求，使用dispatch方法即可，第一个参数就是action内的方法名，而第二个参数就是传递的参数
    // 而由于使用了betterscroll组件，其必须在所有数据取得并且上树后才能生效，所以可以在axios.then取得数据后再.then
    // 再结合nextTick就可以做到
    // if (!this.$store.state.cinemas.length) {  //就写法会.value很多次繁琐
    if (!this.cinemas.length) {
      // 这是mapstate的新写法
      // this.$store.dispatch("getCinemas").then(() => {  //旧写法
      this.getCinemas().then(() => {
        // mapActions新写法
        // 通过promise .then的特性, 再数据取回后上树后再new betterScroll
        this.$nextTick(() => {
          new betterScroll('.content-box', {
            scrollbar: {
              fade: true
            }
          })
        })
      })
    } else {
      // 页面再次打开,缓存取时不需要异步请求数据,数据存在直接用,直接等上树后就可以new betterScroll
      this.$nextTick(() => {
        new betterScroll('.content-box', {
          scrollbar: {
            fade: true
          }
        })
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.header {
  box-shadow: 0 0.0225rem 0.0225rem rgba(95, 95, 95, 0.411);
  .city {
    display: inline-block;
    max-width: 3.75rem;
    font-size: 1rem;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
  }
}
.content-box {
  position: relative;
  overflow: hidden;
  .cinema {
    position: relative;
    padding: 0.9375rem;
    font-size: 0.8125rem;
  }
  .name {
    font-size: 0.9375rem;
  }
  .price {
    display: inline-block;
    position: absolute;
    right: 6%;
    color: rgb(255, 94, 0);
    .price-number {
      font-size: 1rem;
    }
  }
  .address {
    color: rgb(124, 124, 124);
    margin-top: 0.3125rem;
    width: 16rem;
    white-space: nowrap;
    text-overflow: ellipsis;
    overflow: hidden;
  }
  .cross-line {
    position: absolute;
    bottom: 0;
    left: 5%;
    width: 87%;
    border-bottom: 0.0031rem solid rgba(189, 189, 189, 0.767);
  }
}
</style>
